package cn.lg.soar.common.util.token;

import cn.lg.soar.common.data.Soar64;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 动态SoarJWT
 * 密钥定时更新且无法获取，所以无法伪造token，具备高安全性
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class DynamicSoarJwt {

    private long duration;
    private SoarJWT soarJWT;
    private volatile SoarJWT.Decoder[] decoders = new SoarJWT.Decoder[2];
    private int current  = decoders.length - 1;

    private TimerTask timerTask;

    public DynamicSoarJwt(){
        this.init(1800000);
    }

    public DynamicSoarJwt(long duration){
        this.init(duration);
    }

    private synchronized void init(long duration){
        if(null != this.timerTask){
            return;
        }
        DynamicSoarJwt vm = this;
        vm.duration = duration;

        vm.timerTask = new TimerTask() {
            @Override
            public synchronized void run() {
                vm.soarJWT = new SoarJWT(Soar64.ofLong(new Random().nextLong()), vm.duration);
                vm.current ++;
                if(vm.current >= vm.decoders.length){
                    vm.current = 0;
                }
                vm.decoders[ vm.current ] = vm.soarJWT.decoder;
            }
        };
        vm.timerTask.run();
        new Timer().scheduleAtFixedRate(vm.timerTask, vm.duration/2, vm.duration/2);
    }

    public long getDuration(){
        return duration;
    }

    public String create(String payload, String salt){
        return this.soarJWT.create(payload, salt) + SoarJWT.JOIN + current;
    }

    public String create(Object payload, String salt){
        return this.soarJWT.create(payload, salt) + SoarJWT.JOIN + current;
    }

    public String create(String payload){
        return this.soarJWT.create(payload) + SoarJWT.JOIN + current;
    }

    public String create(Object payload){
        return this.soarJWT.create(payload) + SoarJWT.JOIN + current;
    }

    public SoarJWT.Result verify(String token) {
        String[] strings = token.split(SoarJWT.SPLIT);
        if (strings.length < 4){
            return new SoarJWT.Result("format");
        }
        int index = Integer.parseInt(strings[3]);
        if(this.decoders[index] == null){
            return new SoarJWT.Result("index");
        }
        return this.decoders[index].verify(token);
    }

    public SoarJWT.Result verify(String token, String salt) {
        String[] strings = token.split(SoarJWT.SPLIT);
        if (strings.length < 4){
            return new SoarJWT.Result("format");
        }
        int index = Integer.parseInt(strings[3]);
        if(this.decoders[index] == null){
            return new SoarJWT.Result("index");
        }
        return this.decoders[index].verify(token, salt);
    }

    public SoarJWT.Result verifyIgnoreTime(String token) {
        String[] strings = token.split(SoarJWT.SPLIT);
        if (strings.length < 4){
            return new SoarJWT.Result("format");
        }
        int index = Integer.parseInt(strings[3]);
        if(this.decoders[index] == null){
            return new SoarJWT.Result("index");
        }
        return this.decoders[index].verifyIgnoreTime(token);
    }

    public SoarJWT.Result verifyIgnoreTime(String token, String salt) {
        String[] strings = token.split(SoarJWT.SPLIT);
        if (strings.length < 4){
            return new SoarJWT.Result("format");
        }
        int index = Integer.parseInt(strings[3]);
        if(this.decoders[index] == null){
            return new SoarJWT.Result("index");
        }
        return this.decoders[index].verifyIgnoreTime(token, salt);
    }

}
